/**
 * @author Jonathan Schemoul
 */
var mapper = new Class({
	Implements: [Events, Options],
	options: {
		zoomLevel: 12,
		mapControls: new GLargeMapControl(),
		addMapTypeControls: false,
		customIcon: false,
		centerOnDefaultLocation: true,
		defaultLocationCoord: false,
		defaultLocationText: "Paris, France",
		tooltipClass: "map-tips",
		tooltipOpacity: .8,
		clickableAfterExpand: false,
		markerPrefix: 'images/',
		markers: {
			'bar': 'map1-drink',
			'restaurant': 'map1-eat',
			'select': 'map1-select'
		},
		fixFloat: false
	},
	initialize: function(element, options) {
		this.element = $(element);
		this.addresses = [];
		this.setOptions(options);
		this.geocoder = new GClientGeocoder();
		this.map = new GMap2(this.element);
		this.map.addControl(this.options.mapControls);
		this.initIcons();
		if (!this.options.customIcon)
			this.markerOptions = { icon:this.locIcon };
		else
			this.markerOptions = { icon:this.options.customIcon };
		if (this.options.centerOnDefaultLocation)
		{
			if(!this.options.defaultLocationCoord)
				this.geocoder.getLatLng(
					this.options.defaultLocationText,
					function(point) {
					  if (!point) {
						//alert(address + " not found");
					  } else {
						this.map.setCenter(point, this.options.zoomLevel);
					  }
					}.bind(this)
				);
			else
			{
				this.map.setCenter(
					new GLatLng(
						this.options.defaultLocationCoord[0],
						this.options.defaultLocationCoord[1]
					),
					this.options.zoomLevel
				);
			}
		}
		this.fireEvent('onInitialized');
	},
	addAddress: function(options) {
		if (typeof(options.lat) != "undefined")
		{
			var marker = this.addMarker(new GLatLng(options.lat, options.lng), options);
			marker.markerType=options.type;
			if(window.ie)
				markerSuffix = '.gif';
			else
				markerSuffix = '.png';
			if (options.type)
			{
				marker.defaultImage = this.options.markerPrefix + this.options.markers[options.type] + markerSuffix;
				marker.selectImage = this.options.markerPrefix + this.options.markers["select"] + markerSuffix;
				marker.setImage(marker.defaultImage);
				marker.select = function(marker) {
					marker.setImage(marker.selectImage);
					marker.showTip();
				}.pass(marker, this);
				marker.unselect = function(marker) {
					marker.setImage(marker.defaultImage);
					marker.hideTip();
				}.pass(marker, this);
			}
			
			this.addresses.push($H(options).extend({
				'marker': marker
			}));
		} else {
			this.geocoder.getLatLng(
				options.address,
				function(point) {
				  if (!point) {
					//alert(address + " not found");
				  } else {
					options = $H(options).extend({
						lat: point.lat(),
						lng: point.lng()
					});
					this.addAddress(options);
				  }
				}.bind(this)
			);
		}
		
	},
	clearAddresses: function() {
		this.addresses.each(function(address){
			this.map.removeOverlay(address.marker);
		}.bind(this));
		this.addresses = [];
	},
	addMarker: function(point, options) {
		var marker = new GMarker(point, this.markerOptions);
		this.map.addOverlay(marker);
		this.initToolTip(marker, options);
		return marker;
	},
	initToolTip: function(marker, options)
	{
		// Initialize ToolTips Engine
		marker.toolTip = new Element('div', {
			'class': this.options.tooltipClass,
			'styles': {
				'position': 'absolute',
				'bottom': '0',
				'left': '0',
				'visibility': 'hidden',
				'opacity': 0
			}
		}, document).inject(document.body);
		
		marker.toolTipWrapper = new Element('div').inject(marker.toolTip);
		marker.toolTipEffect = new Fx.Styles(marker.toolTip);
		lastmarker=marker;
		marker.linkUrl = options.link;
		marker.showTip = function (marker) {
			// Re-position it
			tooltipSize = marker.toolTip.getSize().size;
			markerDomObject = $(marker.am);
			markerSize = markerDomObject.getSize().size;
			markerPosition = markerDomObject.getPosition();
			
			// Here goes crappy code because IE coders are sadists.
			addX = 0;
			addY = 0; 
			if (Browser.Engine.trident4)
				addY += document.getScroll().y;
			if (this.options.fixFloat&&window.ie)
				addX = -40;
			// End of crappy code.
				
			marker.toolTip.setStyles({
				'bottom': (document.window.getHeight() - markerPosition.y - markerSize.y + addY)  + "px",
				'left': (markerPosition.x - tooltipSize.x + markerSize.x + addX) + "px"
			});
			
			// Set HTML
			marker.toolTip.setHTML(this.formatTip(options));
			
			// Init Effects
			moreinfo = marker.toolTip.getElement('p.moreinfo');
			marker.slider = new Fx.Slide(moreinfo, {duration: 500});
			marker.slider.hide();
			marker.btnslider = new Fx.Slide(marker.toolTip.getElement('p.seemore'), {duration: 500});
			marker.toolTip.getElement('a.seemore').addEvent('click', function(marker) {
				marker.btnslider.slideOut('vertical');
				marker.slider.slideIn('vertical');
				if (this.options.clickableAfterExpand) {
					targetElement = marker.toolTip.getElement('p.moreinfo');
					targetElement.setStyle('cursor', 'pointer');
					targetElement.addEvent('click', function(url){
						window.location.href = url;
					}.pass(marker.linkUrl, this));
				}
			}.pass(marker, this));
			
			// Show it
			marker.toolTipEffect.clearChain();
			marker.toolTip.setStyles({
				'visibility': 'visible'
			});
			marker.toolTipEffect.start({'opacity': this.options.tooltipOpacity});
		}.bind(this, marker);
		marker.hideTip = function(marker) {
			marker.toolTipEffect.start({'opacity': 0}).chain(function(marker) {
				marker.toolTip.setStyle('visibility', 'hidden');
			}.pass(marker, this));
			/*marker.toolTip.setStyles({
				'opacity': 0,
				'visibility': 'hidden'
			});*/
		}.pass(marker, this);
		$(marker.Zk[0]).addEvent('mouseenter', marker.showTip);
		marker.toolTip.addEvent('mouseleave', marker.hideTip);
	},
	formatTip: function(options)
	{
		return '<h4>'
		+ '<a href="' + options.link + '">'
		+ options.label
		+ '</a></h4><div class="tipcontent">'
		+ '<p class="moreinfo">' + options.formatted_address + '</p>'
		+ '<p class="seemore"><a class="seemore">' + 'click to get more info >>' + '</a></p>'
		+'</div>';
	},
	getLatLngRange: function()
	{
		bounds = this.map.getBounds();
		sw = bounds.getSouthWest();
		ne = bounds.getNorthEast();
		range = {
			'lat': [sw.lat(), ne.lat()],
			'lng': [sw.lng(), ne.lng()]
		}
		return range;
	},
	setCenter: function(lat, lng)
	{
		this.map.setCenter(
				new GLatLng(
				parseFloat(lat),
				parseFloat(lng)
				)
			);
	},
	setZoom: function(zoomLevel)
	{
		this.map.setZoom(zoomLevel);
	},
	setCenterAndZoom: function(lat, lng, zoomLevel)
	{
		this.map.setCenter(
			new GLatLng(
			parseFloat(lat),
			parseFloat(lng)
			),
			zoomLevel
		);
	},
	initIcons: function() {
		var locIcon = new GIcon();
		locIcon.iconSize = new GSize(30, 30);
		locIcon.shadowSize = new GSize(0, 0);
		locIcon.iconAnchor = new GPoint(1, 27);
		locIcon.infoWindowAnchor = new GPoint(27, 3);
		locIcon.infoShadowAnchor = new GPoint(1, 27);
		if(window.ie)
			markerSuffix = '.gif';
		else
			markerSuffix = '.png';
		locIcon.image = this.options.markerPrefix + this.options.markers["select"] + markerSuffix;
		this.locIcon = locIcon;
	}
});